using System;
using Parser = Velocity4Net.Runtime.Parse.Parser;
using MethodInvocationException = Velocity4Net.Errors.MethodInvocationException;
using Velocity4Net.Ctx;
namespace Velocity4Net.Runtime.Parse.AST
{

    /// <summary> Please look at the Parser.jjt file which is
    /// what controls the generation of this class.
    /// *
    /// </summary>
    /// <author> <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
    /// </author>
    /// <author> <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
    /// </author>
    /// <version> $Id: ASTAndNode.cs,v 1.3 2003/10/27 13:54:10 corts Exp $
    ///
    /// </version>
    public class ASTAndNode : SimpleNode
    {
        public ASTAndNode(int id) : base(id) { }

        public ASTAndNode(Parser p, int id) : base(p, id) { }

        /// <summary>  Returns the value of the expression.
        /// Since the value of the expression is simply the boolean
        /// result of evaluate(), lets return that.
        /// </summary>
        public override System.Object GetValue(InternalContextAdapter context)
        {
            return Evaluate(context);
        }

        /// <summary> logical and :
        /// null && right = false
        /// left && null = false
        /// null && null = false
        /// </summary>
        public override bool Evaluate(InternalContextAdapter context)
        {
            INode left = jjtGetChild(0);
            INode right = jjtGetChild(1);

            /*
            *  if either is null, lets log and bail
            */

            if (left == null || right == null)
            {
                rsvc.error((left == null ? "Left" : "Right") + " side of '&&' operation is null." + " Operation not possible. " + context.CurrentTemplateName + " [line " + Line + ", column " + Column + "]");
                return false;
            }

            /*
            *  short circuit the test.  Don't eval the RHS if the LHS is false
            */

            if (left.Evaluate(context))
            {
                if (right.Evaluate(context))
                {
                    return true;
                }
            }

            return false;
        }
    }
}
